﻿import { RouteModal, AcModal, ItemAuthModal } from '@@/hw-auth/modal.d';
import { sourceData } from '@@/hw-auth/sourceData';

type AcsModal = Record<string, AcModal>;
export interface AuthDataModal {
  routes: RouteModal;
  apis: AcsModal;
  components: AcsModal;
}
interface AuthResultModal {
  routes: RouteModal[];
  authData: AuthDataModal;
}
class SourceDataControlModal {
  authData: AuthDataModal = {
    routes: {},
    apis: {},
    components: {},
  }; //权限对象

  routes: RouteModal[] = [];

  setData(childRoute?: RouteModal[] | RouteModal) {
    const nowChildRoute = this.initChildAuth(childRoute);
    const { routes, authData } = this.mkData(sourceData.routes, nowChildRoute);

    this.routes = routes;
    this.authData = authData;
  } //初始化方法
  initChildAuth(childRoute?: RouteModal[] | RouteModal, rootAppKey?: string) {
    if (!childRoute) {
      return [];
    }

    const nowChildRoutes = Array.isArray(childRoute)
      ? childRoute
      : [childRoute];

    return nowChildRoutes.map(item => {
      const { appKey, auth, routes, ...data } = item;
      const itemAppKey = appKey || rootAppKey;
      const itemAuth = this.mkChildRouteAuth(auth, itemAppKey);
      return {
        appKey: itemAppKey,
        auth: itemAuth,
        routes: this.initChildAuth(routes, itemAppKey),
        ...data,
      };
    });
  } //初始化子应用pKey
  mkChildRouteAuth(auth: AcModal, appKey?: string) {
    if (!appKey) {
      return auth;
    }

    if (!auth || typeof auth === 'string') {
      return {
        pkey: appKey,
        key: auth,
      };
    }

    if (auth.pkey) {
      return auth;
    }

    return {
      pkey: appKey,
      ...auth,
    };
  } //初始化子应用auth拼接
  defaultAuthData() {
    return {
      routes: {},
      apis: {},
      components: {},
    };
  }

  mkData(rootRoute: RouteModal[], childRoute: RouteModal[]): AuthResultModal {
    const resultRoutes: RouteModal[] = [];
    let authData = this.defaultAuthData();

    rootRoute.forEach(item => {
      const { flatChildApp } = item;
      const resultRoute = this.mkItemRouteData(item, childRoute);
      if (flatChildApp) {
        resultRoutes.push(...resultRoute);
        authData = this.mkAuthData(resultRoute, authData);
        return;
      } //全部替换只需要提取路由权限
      const itemRoute = resultRoute[0];
      const resultItemRoute = { ...itemRoute };
      const resultItemChildRoutes = resultItemRoute.routes;
      if (resultItemChildRoutes) {
        const { routes: childRoutes, authData: childAuthData } = this.mkData(
          resultItemChildRoutes,
          childRoute,
        );
        resultItemRoute.routes = childRoutes;
        authData = this.mergeAuth(authData, childAuthData);
      }
      resultRoutes.push(resultItemRoute);
      authData = this.mkAuthData([item], authData);
    });

    return {
      routes: resultRoutes,
      authData,
    };
  } //构建数据

  mergeAuth(
    authData: AuthDataModal,
    childAuthData: AuthDataModal,
  ): AuthDataModal {
    return {
      routes: Object.assign(authData.routes, childAuthData.routes),
      components: Object.assign(authData.components, childAuthData.components),
      apis: Object.assign(authData.apis, childAuthData.apis),
    };
  } //合并权限

  mkAuthData(route: RouteModal[], authData: AuthDataModal) {
      const nowAuthData = { ...authData };

      route.forEach(item => {
        const {path, isChild, apis, components } = item;
        nowAuthData.routes[path] = item;
        if (isChild) {
          return;
        }
        nowAuthData.components = this.mkComponentsAuthData(
          components,
          nowAuthData.components,
        );
        nowAuthData.apis = this.mkApisAuthData(apis, nowAuthData.apis);
      });

      return nowAuthData;
    } //权限构建

  mkApisAuthData(apis: ItemAuthModal[], apisAuthData: AcsModal) {
    const apisAuthObj: AcsModal = {};

    apis.forEach(item => {
      const { path, ...auth } = item;
      if (path) {
        apisAuthObj[path] = auth;
      }
    });
    return Object.assign(apisAuthData, apisAuthObj);
  } //构建apis权限

  mkComponentsAuthData(components: AcModal[], componentsAuthData: AcsModal) {
    const componentsAuthObj: AcsModal = {};
    components.forEach(item => {
      const resultKey = this.separateAuthKey(item);
      if (resultKey) {
        componentsAuthObj[resultKey] = item;
      }
    });
    return Object.assign(componentsAuthData, componentsAuthObj);
  } //构建components权限

  separateAuthKey(itemAuth: AcModal) {
    if (!itemAuth) {
      return null;
    }
    if (typeof itemAuth === 'string') {
      return itemAuth;
    }
    return itemAuth.key;
  } //分离key

  mkItemRouteData(route: RouteModal, childRoute: RouteModal[]): RouteModal[] {
    const { childAppKey, flatChildApp, routes = [] } = route;

    if (!childAppKey) {
      return [route];
    }

    const resultChildRoute = this.mkChildRoute(route, childRoute);

    if (flatChildApp) {
      return resultChildRoute;
    }

    return [
      {
        ...route,
        routes: [...resultChildRoute, ...routes],
      },
    ];
  } //构建单个路由

  mkChildRoute(route: RouteModal, childRoute: RouteModal[]): RouteModal[] {
    const { path, childAppKey } = route;

    const nowChildAppKey: string[] = Array.isArray(childAppKey)
      ? childAppKey
      : [childAppKey as string];

    const itemChildRoute = this.findChildRoute(nowChildAppKey, childRoute);

    return this.addBaseNameAndFlag(itemChildRoute, path);
  } //查找当前路由包含的childAppKey

  findChildRoute(
    childAppKey: string[],
    childRoute: RouteModal[],
  ): RouteModal[] {
    const resultChildRoute: RouteModal[] = [];

    childAppKey.forEach(item => {
      const childItem = this.matchChildKey(item, childRoute);
      if (childItem) {
        resultChildRoute.push(childItem);
      }
    });

    return resultChildRoute;
  } //查找子模块

  matchChildKey(key: string, childRoute: RouteModal[]): RouteModal | undefined {
    return childRoute.find(item => {
      const { appKey } = item;
      return key === appKey;
    });
  } //匹配子模块

  addBaseNameAndFlag(
    childRoute: RouteModal[],
    baseName?: string,
  ): RouteModal[] {
    return childRoute.map(item => {
      const { routes, path } = item;

      let childRoutes = routes;

      if (routes) {
        childRoutes = this.addBaseNameAndFlag(routes, baseName);
      }

      return {
        ...item,
        path: `${baseName}${path}`,
        baseName,
        isChild: true,
        routes: childRoutes,
      };
    });
  } //添加baseName+isChild标识
}
const authDataFactory = () => {
  const sourceDataControlModal = new SourceDataControlModal();
  sourceDataControlModal.setData();
  const data = sourceDataControlModal.authData;
  const routes = sourceDataControlModal.routes;
  const obj = {
    data,
    routes,
    set: (childRoute?: RouteModal[] | RouteModal) => {
      sourceDataControlModal.setData(childRoute);
      obj.data = sourceDataControlModal.authData;
      obj.routes = sourceDataControlModal.routes;
    },
  };
  return new Proxy(obj, {
    set() {
      console.error('请勿修改对象，调用set方法!');
      return false;
    },
  });
};
export const authData = authDataFactory();
